async function init() {
  // const stats = initStats();
  const renderer = initRenderer();
  const camera = initCamera();
  const trackballControls = initTrackballControls(camera, renderer);
  const clock = new THREE.Clock();
  const scene = new THREE.Scene();
  camera.position.set(20, 0, 150);

  var cloud;

  var controls = new (function () {
    this.size = 5;
    this.transparent = true;
    this.opacity = 0.6;
    this.vertexColors = true;
    this.color = 0xffffff;
    this.vertexColor = 0xffffff;
    this.sizeAttenuation = true;
    this.rotate = true;

    this.redraw = function () {
      if (scene.getObjectByName("particles")) {
        scene.remove(scene.getObjectByName("particles"));
      }
      createParticles(
        controls.size,
        controls.transparent,
        controls.opacity,
        controls.vertexColors,
        controls.sizeAttenuation,
        controls.color,
        controls.vertexColor
      );
    };

    this.drawTexture = function () {
      if (scene.getObjectByName("texture")) {
        scene.remove(scene.getObjectByName("texture"));
      }
      // 加载文字
      drawTexture();
    };

    this.textX = 0;
    this.textY = -80;
    this.textZ = -80;
  })();

  // var gui = new dat.GUI();
  // gui.add(controls, "size", 0, 10).onChange(controls.redraw);
  // gui.add(controls, "transparent").onChange(controls.redraw);
  // gui.add(controls, "opacity", 0, 1).onChange(controls.redraw);
  // gui.add(controls, "vertexColors").onChange(controls.redraw);

  // gui.addColor(controls, "color").onChange(controls.redraw);
  // gui.addColor(controls, "vertexColor").onChange(controls.redraw);
  // gui.add(controls, "sizeAttenuation").onChange(controls.redraw);
  // gui.add(controls, "rotate");

  // gui.add(controls, "textX", -300, 300).onChange(controls.drawTexture);
  // gui.add(controls, "textY", -300, 300).onChange(controls.drawTexture);
  // gui.add(controls, "textZ", -300, 300).onChange(controls.drawTexture);

  controls.redraw();

  //   创建粒子系统
  function createParticles(
    size,
    transparent,
    opacity,
    vertexColors,
    sizeAttenuation,
    colorValue,
    vertexColorValue
  ) {
    const loader = new THREE.TextureLoader();
    const geom = new THREE.Geometry();
    const material = new THREE.PointsMaterial({
      size: size,
      transparent: transparent,
      vertexColors: vertexColors,
      opacity: opacity,
      map: loader.load("./snow.png"),
      sizeAttenuation: sizeAttenuation,
      color: new THREE.Color(colorValue),
    });

    const range = 500;

    for (let i = 0; i < 15000; i++) {
      const particle = new THREE.Vector3(
        Math.random() * range - range / 2,
        Math.random() * range - range / 2,
        Math.random() * range - range / 2
      );
      geom.vertices.push(particle);
      const color = new THREE.Color(vertexColorValue);
      const asHSL = {};
      color.getHSL(asHSL);
      color.setHSL(asHSL.h, asHSL.s, asHSL.l * Math.random());
      geom.colors.push(color);
    }

    cloud = new THREE.Points(geom, material);
    cloud.name = "particles";
    scene.add(cloud);
  }

  // 添加灯光
  addLight();
  function addLight() {
    var keyLight = new THREE.SpotLight(0xffffff);
    keyLight.position.set(00, 80, 80);
    keyLight.intensity = 2;
    keyLight.lookAt(new THREE.Vector3(0, 15, 0));
    keyLight.castShadow = true;
    keyLight.shadow.mapSize.height = 4096;
    keyLight.shadow.mapSize.width = 4096;
    scene.add(keyLight);

    var backlight1 = new THREE.SpotLight(0xaaaaaa);
    backlight1.position.set(150, 40, -20);
    backlight1.intensity = 0.5;
    backlight1.lookAt(new THREE.Vector3(0, 15, 0));
    scene.add(backlight1);

    var backlight2 = new THREE.SpotLight(0xaaaaaa);
    backlight2.position.set(-150, 40, -20);
    backlight2.intensity = 0.5;
    backlight2.lookAt(new THREE.Vector3(0, 15, 0));
    scene.add(backlight2);
  }

  // 加载圣诞树
  async function loadTree() {
    const path = {
      asset: "./",
      mtl: "./model/12150_Christmas_Tree_V2_L2.mtl",
      obj: "./model/12150_Christmas_Tree_V2_L2.obj",
    };

    // https://tech.suitbim.com/static/

    // const path = {
    //   asset: "https://tech0.suitbim.com.cn/static/model/",
    //   mtl: "./12150_Christmas_Tree_V2_L2.mtl",
    //   obj: "https://tech0.suitbim.com.cn/static/model/12150_Christmas_Tree_V2_L2.obj",
    // };

    // const path= {
    //   asset:'../../assets/models/butterfly/',
    //   mtl:'butterfly.mtl',
    //   obj:'../../assets/models/butterfly/butterfly.obj'
    // }
    const mtlLoader = new THREE.MTLLoader();
    mtlLoader.setPath(path.asset);
    const materials = await new Promise((resolve) => {
      mtlLoader.load(path.mtl, resolve);
    });
    const loader = new THREE.OBJLoader();
    materials.preload();
    loader.setMaterials(materials);

    let tree = {};
    loader.load(path.obj, function (mesh) {
      // var material = new THREE.MeshBasicMaterial({
      //   // color: "red",
      // });

      // // loadedMesh is a group of meshes. For
      // // each mesh set the material, and compute the information
      // // three.js needs for rendering.
      mesh.children.forEach(function (child) {
        // child.material = material;
        // child.geometry.computeVertexNormals();
        // child.geometry.computeFaceNormals();

        child.material.opacity = 0.9;
        child.material.transparent = true;
        child.material.depthTest = false;
        child.material.side = THREE.DoubleSide;
      });

      const scale = 0.5;
      mesh.scale.set(scale, scale, scale);
      mesh.rotation.x = -0.5 * Math.PI;
      mesh.position.y -= 30;
      scene.add(mesh);

      tree.mesh = mesh;

      renderer.render(scene, camera);
    });

    return tree;
  }

  // 加载文字
  const textureMesh = await drawTexture();
  async function drawTexture({
    size = 16,
    height = 10,
    weight = true,
    x = controls.textX,
    y = controls.textY,
    z = controls.textZ,
  } = {}) {
    const font = await new Promise((resolve) => {
      new THREE.FontLoader().load(
        "./small-test.json",
        (res) => {
          resolve(res);
        }
      );
    });
    // 创建文本几何体
    const options = {
      size, // 字体大小
      height, // 字体的z轴的高度
      weight, // 是否加粗
      font, // 字体
    };
    const geom = new THREE.TextGeometry("榕榕宝贝,圣诞快乐", options);
    geom.translate(-100, 0, 0);
    geom.applyMatrix(new THREE.Matrix4().makeScale(0.5, 0.5, 0.5));

    const material = new THREE.MeshNormalMaterial(); // 法向量材质
    material.side = THREE.DoubleSide;
    const mesh = new THREE.Mesh(geom, material);
    if (x) mesh.position.x = x;
    if (y) mesh.position.y = y;
    if (z) mesh.position.z = z;

    mesh.rotation.z = (2 * Math.PI) / 180;
    mesh.rotation.x = (-10 * Math.PI) / 180;
    mesh.name = "texture";
    scene.add(mesh);

    return mesh;
  }

  function loadAudio(mesh) {
    // const path = "./c_happy.mp3";
    const path ='https://tech0.suitbim.com.cn/static/model/c_happy.mp3'
    // 先创建listener
    const listener = new THREE.AudioListener();
    // 向相机中添加监听器
    camera.add(listener);

    // 再创建位置声音
    const posSound = new THREE.PositionalAudio(listener);

    // 再创建声音加载器加载声音
    const audioLoader = new THREE.AudioLoader();
    audioLoader.load(path, function (buffer) {
      posSound.setBuffer(buffer);
      posSound.setRefDistance(50); // 设置距离
      posSound.play();
      posSound.setRolloffFactor(10);
      posSound.setLoop(true);
    });

    if (mesh) {
      mesh.add(posSound);
    }

    return posSound;
  }

  const tree = await loadTree();
  let step = 0;

  // 加载声音
  const posSound = loadAudio(tree.mesh);
  window.addEventListener("click", () => {
    console.log(posSound);
    posSound.stop();
    posSound.play();
  });
  let textureStep = 0;
  let flag = true;
  //  渲染
  render();

  function render() {
    // stats.update();

    trackballControls.update(clock.getDelta());
    if (controls.rotate) {
      step += 0.01;
      cloud.rotation.x = step;
      cloud.rotation.z = step;
      cloud.rotation.y = step;
      const range = Math.PI*0.10
      textureStep += 0.01;
      textureMesh.rotation.y = Math.sin(textureStep)*range;
    }
    if (tree.mesh) {
      tree.mesh.rotation.z += 0.05;
    }

    requestAnimationFrame(render);
    renderer.render(scene, camera);
  }
}
